home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / gnu / cvs-1_3.lha / cvs-1.3 / src / entries.c < prev    next >
C/C++ Source or Header  |  1992-03-31  |  11KB  |  489 lines

  1. /*
  2.  * Copyright (c) 1992, Brian Berliner and Jeff Polk
  3.  * Copyright (c) 1989-1992, Brian Berliner
  4.  * 
  5.  * You may distribute under the terms of the GNU General Public License as
  6.  * specified in the README file that comes with the CVS 1.3 kit.
  7.  * 
  8.  * Entries file to Files file
  9.  * 
  10.  * Creates the file Files containing the names that comprise the project, from
  11.  * the Entries file.
  12.  */
  13.  
  14. #include "cvs.h"
  15.  
  16. #ifndef lint
  17. static char rcsid[] = "@(#)entries.c 1.37 92/03/31";
  18. #endif
  19.  
  20. #if __STDC__
  21. static Node *AddEntryNode (List * list, char *name, char *version,
  22.                char *timestamp, char *options, char *tag,
  23.                char *date);
  24. #else
  25. static Node *AddEntryNode ();
  26. #endif                /* __STDC__ */
  27.  
  28. static FILE *entfile;
  29. static char *entfilename;        /* for error messages */
  30.  
  31. /*
  32.  * Write out the line associated with a node of an entries file
  33.  */
  34. static int
  35. write_ent_proc (node)
  36.     Node *node;
  37. {
  38.     Entnode *p;
  39.  
  40.     p = (Entnode *) node->data;
  41.     if (fprintf (entfile, "/%s/%s/%s/%s/", node->key, p->version,
  42.          p->timestamp, p->options) == EOF)
  43.     error (1, errno, "cannot write %s", entfilename);
  44.     if (p->tag)
  45.     {
  46.     if (fprintf (entfile, "T%s\n", p->tag) == EOF)
  47.         error (1, errno, "cannot write %s", entfilename);
  48.     }
  49.     else if (p->date)
  50.     {
  51.     if (fprintf (entfile, "D%s\n", p->date) == EOF)
  52.         error (1, errno, "cannot write %s", entfilename);
  53.     }
  54.     else if (fprintf (entfile, "\n") == EOF)
  55.     error (1, errno, "cannot write %s", entfilename);
  56.     return (0);
  57. }
  58.  
  59. /*
  60.  * write out the current entries file given a list,  making a backup copy
  61.  * first of course
  62.  */
  63. static void
  64. write_entries (list)
  65.     List *list;
  66. {
  67.     /* open the new one and walk the list writing entries */
  68.     entfilename = CVSADM_ENTBAK;
  69.     entfile = open_file (entfilename, "w+");
  70.     (void) walklist (list, write_ent_proc);
  71.     if (fclose (entfile) == EOF)
  72.     error (1, errno, "error closing %s", entfilename);
  73.  
  74.     /* now, atomically (on systems that support it) rename it */
  75.     rename_file (entfilename, CVSADM_ENT);
  76. }
  77.  
  78. /*
  79.  * Removes the argument file from the Entries file if necessary.
  80.  */
  81. void
  82. Scratch_Entry (list, fname)
  83.     List *list;
  84.     char *fname;
  85. {
  86.     Node *node;
  87.  
  88.     if (trace)
  89.     (void) fprintf (stderr, "-> Scratch_Entry(%s)\n", fname);
  90.  
  91.     /* hashlookup to see if it is there */
  92.     if ((node = findnode (list, fname)) != NULL)
  93.     {
  94.     delnode (node);            /* delete the node */
  95.     if (!noexec)
  96.         write_entries (list);    /* re-write the file */
  97.     }
  98. }
  99.  
  100. /*
  101.  * Enters the given file name/version/time-stamp into the Entries file,
  102.  * removing the old entry first, if necessary.
  103.  */
  104. void
  105. Register (list, fname, vn, ts, options, tag, date)
  106.     List *list;
  107.     char *fname;
  108.     char *vn;
  109.     char *ts;
  110.     char *options;
  111.     char *tag;
  112.     char *date;
  113. {
  114.     Node *node;
  115.  
  116.     if (trace)
  117.     (void) fprintf (stderr, "-> Register(%s, %s, %s, %s, %s %s)\n",
  118.             fname, vn, ts, options, tag ? tag : "",
  119.             date ? date : "");
  120.     /* was it already there? */
  121.     if ((node = findnode (list, fname)) != NULL)
  122.     {
  123.     /* take it out */
  124.     delnode (node);
  125.  
  126.     /* add the new one and re-write the file */
  127.     (void) AddEntryNode (list, fname, vn, ts, options, tag, date);
  128.     if (!noexec)
  129.         write_entries (list);
  130.     }
  131.     else
  132.     {
  133.     /* add the new one */
  134.     node = AddEntryNode (list, fname, vn, ts, options, tag, date);
  135.  
  136.     if (!noexec)
  137.     {
  138.         /* append it to the end */
  139.         entfilename = CVSADM_ENT;
  140.         entfile = open_file (entfilename, "a");
  141.         (void) write_ent_proc (node);
  142.         if (fclose (entfile) == EOF)
  143.         error (1, errno, "error closing %s", entfilename);
  144.     }
  145.     }
  146. }
  147.  
  148. /*
  149.  * Node delete procedure for list-private sticky dir tag/date info
  150.  */
  151. static void
  152. freesdt (p)
  153.     Node *p;
  154. {
  155.     struct stickydirtag *sdtp;
  156.  
  157.     sdtp = (struct stickydirtag *) p->data;
  158.     if (sdtp->tag)
  159.     free (sdtp->tag);
  160.     if (sdtp->date)
  161.     free (sdtp->date);
  162.     if (sdtp->options)
  163.     free (sdtp->options);
  164.     free ((char *) sdtp);
  165. }
  166.  
  167. /*
  168.  * Read the entries file into a list, hashing on the file name.
  169.  */
  170. List *
  171. ParseEntries (aflag)
  172.     int aflag;
  173. {
  174.     List *entries;
  175.     char line[MAXLINELEN];
  176.     char *cp, *user, *vn, *ts, *options;
  177.     char *tag_or_date, *tag, *date;
  178.     char *dirtag, *dirdate;
  179.     int lineno = 0;
  180.     FILE *fpin;
  181.  
  182.     /* get a fresh list... */
  183.     entries = getlist ();
  184.  
  185.     /*
  186.      * Parse the CVS/Tag file, to get any default tag/date settings. Use
  187.      * list-private storage to tuck them away for Version_TS().
  188.      */
  189.     ParseTag (&dirtag, &dirdate);
  190.     if (aflag || dirtag || dirdate)
  191.     {
  192.     struct stickydirtag *sdtp;
  193.  
  194.     sdtp = (struct stickydirtag *) xmalloc (sizeof (*sdtp));
  195.     bzero ((char *) sdtp, sizeof (*sdtp));
  196.     sdtp->aflag = aflag;
  197.     sdtp->tag = xstrdup (dirtag);
  198.     sdtp->date = xstrdup (dirdate);
  199.  
  200.     /* feed it into the list-private area */
  201.     entries->list->data = (char *) sdtp;
  202.     entries->list->delproc = freesdt;
  203.     }
  204.  
  205.   again:
  206.     fpin = fopen (CVSADM_ENT, "r");
  207.     if (fpin == NULL)
  208.     error (0, errno, "cannot open %s for reading", CVSADM_ENT);
  209.     else
  210.     {
  211.     while (fgets (line, sizeof (line), fpin) != NULL)
  212.     {
  213.         lineno++;
  214.         if (line[0] == '/')
  215.         {
  216.         user = line + 1;
  217.         if ((cp = index (user, '/')) == NULL)
  218.             continue;
  219.         *cp++ = '\0';
  220.         vn = cp;
  221.         if ((cp = index (vn, '/')) == NULL)
  222.             continue;
  223.         *cp++ = '\0';
  224.         ts = cp;
  225.         if ((cp = index (ts, '/')) == NULL)
  226.             continue;
  227.         *cp++ = '\0';
  228.         options = cp;
  229.         if ((cp = index (options, '/')) == NULL)
  230.             continue;
  231.         *cp++ = '\0';
  232.         tag_or_date = cp;
  233.         if ((cp = index (tag_or_date, '\n')) == NULL)
  234.             continue;
  235.         *cp = '\0';
  236.         tag = (char *) NULL;
  237.         date = (char *) NULL;
  238.         if (*tag_or_date == 'T')
  239.             tag = tag_or_date + 1;
  240.         else if (*tag_or_date == 'D')
  241.             date = tag_or_date + 1;
  242.         (void) AddEntryNode (entries, user, vn, ts, options, tag, date);
  243.         }
  244.         else
  245.         {
  246.         /* try conversion only on first line */
  247.         if (lineno == 1)
  248.         {
  249.             (void) fclose (fpin);
  250.             check_entries ((char *) NULL);
  251.             goto again;
  252.         }
  253.         }
  254.     }
  255.     }
  256.  
  257.     /* clean up and return */
  258.     if (fpin)
  259.     (void) fclose (fpin);
  260.     if (dirtag)
  261.     free (dirtag);
  262.     if (dirdate)
  263.     free (dirdate);
  264.     return (entries);
  265. }
  266.  
  267. /*
  268.  * Look at the entries file to determine if it is in the old entries format.
  269.  * If so, convert it to the new format.
  270.  */
  271. void
  272. check_entries (dir)
  273.     char *dir;
  274. {
  275.     FILE *fpin, *fpout;
  276.     char tmp[MAXLINELEN];
  277.     char line[MAXLINELEN];
  278.     char entname[MAXLINELEN];
  279.     char entbak[MAXLINELEN];
  280.     char *cp, *user, *rev, *ts, *opt;
  281.  
  282.     if (dir != NULL)
  283.     {
  284.     (void) sprintf (entname, "%s/%s", dir, CVSADM_ENT);
  285.     (void) sprintf (entbak, "%s/%s", dir, CVSADM_ENTBAK);
  286.     }
  287.     else
  288.     {
  289.     (void) strcpy (entname, CVSADM_ENT);
  290.     (void) strcpy (entbak, CVSADM_ENTBAK);
  291.     }
  292.  
  293.     fpin = open_file (entname, "r");
  294.     if (fgets (line, sizeof (line), fpin) == NULL)
  295.     {
  296.     (void) fclose (fpin);
  297.     return;
  298.     }
  299.     (void) fclose (fpin);
  300.     if (line[0] != '/')
  301.     {
  302.     rename_file (entname, entbak);
  303.     fpin = open_file (entbak, "r");
  304.     fpout = open_file (entname, "w+");
  305.     while (fgets (line, sizeof (line), fpin) != NULL)
  306.     {
  307.         if (line[0] == '/')
  308.         {
  309.         if (fputs (line, fpout) == EOF)
  310.             error (1, errno, "cannot write %s", CVSADM_ENT);
  311.         continue;
  312.         }
  313.         rev = line;
  314.         if ((ts = index (line, '|')) == NULL)
  315.         continue;
  316.         *ts++ = '\0';
  317.         if ((user = rindex (ts, ' ')) == NULL)
  318.         continue;
  319.         *user++ = '\0';
  320.         if ((cp = index (user, '|')) == NULL)
  321.         continue;
  322.         *cp = '\0';
  323.         opt = "";
  324. #ifdef HAVE_RCS5
  325. #ifdef HAD_RCS4
  326.         opt = "-V4";
  327. #endif
  328. #endif
  329.         if (fprintf (fpout, "/%s/%s/%s/%s/\n", user, rev, ts, opt) == EOF)
  330.         error (1, errno, "cannot write %s", CVSADM_ENT);
  331.     }
  332.     (void) fclose (fpin);
  333.     if (fclose (fpout) == EOF)
  334.         error (1, errno, "cannot close %s", entname);
  335.  
  336.     /* clean up any old Files or Mod files */
  337.     if (dir != NULL)
  338.         (void) sprintf (tmp, "%s/%s", dir, CVSADM_FILE);
  339.     else
  340.         (void) strcpy (tmp, CVSADM_FILE);
  341.     if (isfile (tmp))
  342.         (void) unlink (tmp);
  343.  
  344.     if (dir != NULL)
  345.         (void) sprintf (tmp, "%s/%s", dir, CVSADM_MOD);
  346.     else
  347.         (void) strcpy (tmp, CVSADM_MOD);
  348.     if (isfile (tmp))
  349.         (void) unlink (tmp);
  350.     }
  351. }
  352.  
  353. /*
  354.  * Free up the memory associated with the data section of an ENTRIES type
  355.  * node
  356.  */
  357. static void
  358. Entries_delproc (node)
  359.     Node *node;
  360. {
  361.     Entnode *p;
  362.  
  363.     p = (Entnode *) node->data;
  364.     free (p->version);
  365.     free (p->timestamp);
  366.     free (p->options);
  367.     if (p->tag)
  368.     free (p->tag);
  369.     if (p->date)
  370.     free (p->date);
  371.     free ((char *) p);
  372. }
  373.  
  374. /*
  375.  * Get an Entries file list node, initialize it, and add it to the specified
  376.  * list
  377.  */
  378. static Node *
  379. AddEntryNode (list, name, version, timestamp, options, tag, date)
  380.     List *list;
  381.     char *name;
  382.     char *version;
  383.     char *timestamp;
  384.     char *options;
  385.     char *tag;
  386.     char *date;
  387. {
  388.     Node *p;
  389.     Entnode *entdata;
  390.  
  391.     /* get a node and fill in the regular stuff */
  392.     p = getnode ();
  393.     p->type = ENTRIES;
  394.     p->delproc = Entries_delproc;
  395.  
  396.     /* this one gets a key of the name for hashing */
  397.     p->key = xstrdup (name);
  398.  
  399.     /* malloc the data parts and fill them in */
  400.     p->data = xmalloc (sizeof (Entnode));
  401.     entdata = (Entnode *) p->data;
  402.     entdata->version = xstrdup (version);
  403.     entdata->timestamp = xstrdup (timestamp);
  404.     entdata->options = xstrdup (options);
  405.     if (entdata->options == NULL)
  406.     entdata->options = xstrdup ("");/* must be non-NULL */
  407.     entdata->tag = xstrdup (tag);
  408.     entdata->date = xstrdup (date);
  409.  
  410.     /* put the node into the list */
  411.     if (addnode (list, p) != 0)
  412.     error (0, 0, "Duplicate filename in entries file (%s) -- ignored",
  413.            name);
  414.  
  415.     return (p);
  416. }
  417.  
  418. /*
  419.  * Write out/Clear the CVS/Tag file.
  420.  */
  421. void
  422. WriteTag (dir, tag, date)
  423.     char *dir;
  424.     char *tag;
  425.     char *date;
  426. {
  427.     FILE *fout;
  428.     char tmp[PATH_MAX];
  429.  
  430.     if (noexec)
  431.     return;
  432.  
  433.     if (dir == NULL)
  434.     (void) strcpy (tmp, CVSADM_TAG);
  435.     else
  436.     (void) sprintf (tmp, "%s/%s", dir, CVSADM_TAG);
  437.  
  438.     if (tag || date)
  439.     {
  440.     fout = open_file (tmp, "w+");
  441.     if (tag)
  442.     {
  443.         if (fprintf (fout, "T%s\n", tag) == EOF)
  444.         error (1, errno, "write to %s failed", tmp);
  445.     }
  446.     else
  447.     {
  448.         if (fprintf (fout, "D%s\n", date) == EOF)
  449.         error (1, errno, "write to %s failed", tmp);
  450.     }
  451.     if (fclose (fout) == EOF)
  452.         error (1, errno, "cannot close %s", tmp);
  453.     }
  454.     else
  455.     (void) unlink_file (tmp);
  456. }
  457.  
  458. /*
  459.  * Parse the CVS/Tag file for the current directory.
  460.  */
  461. void
  462. ParseTag (tagp, datep)
  463.     char **tagp;
  464.     char **datep;
  465. {
  466.     FILE *fp;
  467.     char line[MAXLINELEN];
  468.     char *cp;
  469.  
  470.     if (tagp)
  471.     *tagp = (char *) NULL;
  472.     if (datep)
  473.     *datep = (char *) NULL;
  474.     fp = fopen (CVSADM_TAG, "r");
  475.     if (fp)
  476.     {
  477.     if (fgets (line, sizeof (line), fp) != NULL)
  478.     {
  479.         if ((cp = rindex (line, '\n')) != NULL)
  480.         *cp = '\0';
  481.         if (*line == 'T' && tagp)
  482.         *tagp = xstrdup (line + 1);
  483.         else if (*line == 'D' && datep)
  484.         *datep = xstrdup (line + 1);
  485.     }
  486.     (void) fclose (fp);
  487.     }
  488. }
  489.